/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#include "bit_stream.h"


BitStream::BitStream()
{
    m_bp = 0;
}

// writes number of bits to the output buffer and updates the buffer pointer
void BitStream::writeByte( byte_t* buffer, byte_t bits, int number )
{
    int byteIndex = m_bp >> 3;
    int offset =  m_bp - ( ( m_bp >> 3 ) << 3 ); //8 - ( ( ( ( bp + 7 ) & ( ~7 ) ) ) - bp );
    if ( offset == 0 )
    {
        buffer[ byteIndex ] = bits << ( 8 - number );
    }
    else
    {
        if ( offset + number <= 8 )
        {
            buffer[ byteIndex ] |= bits << ( 8 - offset - number );
        }
        else
        {
            buffer[ byteIndex ] |= bits >> ( offset - ( 8 - number ) );
            buffer[ byteIndex + 1 ] = ( byte_t ) ( bits << ( 16 - ( offset + number ) ) );
        }
    }

    m_bp += number;
}

void BitStream::writeShort( byte_t* buffer, unsigned short bits, int number )
{
    if ( number <= 8 )
    {
        writeByte( buffer, ( byte_t ) bits, number );
    }
    else
    {
        writeByte( buffer, ( byte_t ) ( bits >> 8 ), number - 8 );
        writeByte( buffer, ( byte_t ) ( bits & 0x00FF ), 8 );
    }
}

void BitStream::writeBytes( byte_t* buffer, byte_t* bytes, uint_t number, bool invertBits )
{
    uint_t numberOfBytes = number >> 3;
    uint_t lastBits = number - ( numberOfBytes << 3 );

    for ( uint_t i = 0; i < numberOfBytes; i++ )
    {
        writeByte( buffer, invertBits ? ~bytes[ i ] : bytes[ i ], 8 );
    }

    if ( lastBits )
    {
        writeByte( buffer, bytes[ numberOfBytes ] >> ( 7 - lastBits ), lastBits );
    }
}

